﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using Air_condition.DO;
using System.Collections;
using System.Reflection;
using System.Collections.ObjectModel;

namespace Air_condition.BU
{
    public class TemplateManager
    {
        /// The list objects for template
        public ObservableCollection<Room> lroom = new ObservableCollection<Room>();
        public ObservableCollection<InternalLoad> linternalload = new ObservableCollection<InternalLoad>();
        public ObservableCollection<Glass> lglass = new ObservableCollection<Glass>();
        public ObservableCollection<Roof> lroof = new ObservableCollection<Roof>();
        public ObservableCollection<Ceiling> lceiling = new ObservableCollection<Ceiling>();
        public ObservableCollection<Floor> lfloor = new ObservableCollection<Floor>();
        public ObservableCollection<Wall> lwall = new ObservableCollection<Wall>();
        private int iRoom = 0;
        private int iInter = 0;
        private int iCons = 0;

        /// <summary>
        /// Create default template
        /// </summary>
        public void CreateDefault() {
            Room room = new Room();
            InternalLoad inter = new InternalLoad();
            Wall wall = new Wall();
            Floor floor = new Floor();
            Ceiling Ceiling = new Ceiling();
            Glass Glass = new Glass();

            room.sName = "Default";            
            room.dbInsideTemperature = 20;
            room.dbOutsideAirContainingLevel = 1;
            room.dbInsideAirContainingLevel = 1;
            room.dbHeigh = 3.048;
            room.dbWidth = 3.048;
            room.dbLength = 3.048;
            AddNewRoom(room);

            inter.sName = "Default";
            inter.iSpaceConditioning = 0;
            inter.dbDensityPeople = 20;
            inter.iGender = 0;
            inter.dbAirMountForOnePeople = 7.5;
            inter.dbSensibleHeat = 86;
            inter.dbLatentHeat = 44;
            Equip equip = new Equip();
            equip.dbEnergy = 300;
            equip.iType = 0;
            inter.lequip.Add(equip);
            AddNewInternal(inter);

            Glass.iWindowFrameType = 0;
            Glass.sName = "Default";
            Glass.dbArea = 2;
            Glass.iTypeofglass = 0;
            Glass.dbGlassCoefficient = 1;
            Glass.iLatitute = 0;
            Glass.iSolarHour = 0;
            Glass.iMonth = 5;
            Glass.iDirection = 0;
            Glass.iPressure = 1;
            Glass.iTime = 5;
            Glass.dbSolarRadition = 60;
            Glass.dbImmediateCoefficient = 0.06;

            Ceiling.sName = "Default";
            Ceiling.dbWidth = 3.048;
            Ceiling.dbLength = 3.048;
            Ceiling.iStructure = 0;
            Ceiling.iCharacteristics = 0;
            Ceiling.dbHeatTransferCoefficient = 3.14;

            floor.sName = "Default";
            floor.dbWidth = 3.048;
            floor.dbLength = 3.048;
            floor.iStructure = 0;
            floor.iCharacteristics = 0;
            floor.dbHeatTransferCoefficient = 3.14;

            wall.sName = "Default";
            wall.dbWidth = 3.048;
            wall.dbLength = 3.048;
            wall.iTypeExposure = 0;
            wall.icharacteristics = 0;
            wall.dbHeatResistance = 0.111;
            AddnewConstruction(wall,floor, Ceiling, Glass);
        }

        #region Template Room
        /// <summary>
        /// Add a template about Room
        /// </summary>
        /// <param name="room">Room object</param>
        public void AddNewRoom(object room)
        {
            iRoom++;
            Room r1 = (Room)(room);
            lroom.Add(r1);
        }

        /// <summary>
        /// Delete a template about Room
        /// </summary>
        /// <param name="room">Room object that need to delete</param>
        public void DeleteTemplateRoom(object room)
        {
            Room r1 = (Room)(room);
            lroom.Remove(r1);

        }
        
        /// <summary>
        /// Copy a template about Room from a template
        /// </summary>
        /// <param name="oroot">Room object that need to copy</param>
        /// <param name="ocopy">New Room object</param>
        internal void CoppyTemplateRoom(object oroot, object ocopy)
        {
            iRoom++;
            foreach (PropertyInfo i in oroot.GetType().GetProperties())
            {
                object Copy = Activator.CreateInstance<object>();
                object value = oroot.GetType().GetProperty(i.Name).GetValue(oroot, null);
                i.SetValue(ocopy, value, null);
            }

            Room o1copy = (Room)ocopy;
            o1copy.sName = "Room" + "-" + iRoom;
            CheckRoomName(o1copy);
            lroom.Add(o1copy);
        }

        /// <summary>
        /// Check overload name for Template Room
        /// </summary>
        /// <param name="r">Room object</param>
        public void CheckRoomName(Room r)
        {
            foreach (Room ro in lroom)
            {
                if (r.sName == ro.sName)
                {
                    iRoom++;
                    r.sName = "Room-" + iRoom;
                    CheckRoomName(r);
                }
            }
        }
        #endregion

        #region Template Internal Load
        /// <summary>
        /// Add a template about internal load
        /// </summary>
        /// <param name="inter">InternalLoad object</param>
        public void AddNewInternal(object inter)
        {
            iInter++;
            InternalLoad inter1 = (InternalLoad)(inter);
            linternalload.Add(inter1);

        }
        
        /// <summary>
        /// Delete a template about internal load
        /// </summary>
        /// <param name="inter">InternalLoad object that want to delete</param>
        public void DeleteTemplateInternal(object inter)
        {
            InternalLoad intern1 = (InternalLoad)(inter);
            linternalload.Remove(intern1);

        }

        /// <summary>
        /// Copy a template about internal load from a template
        /// </summary>
        /// <param name="oroot">InternalLoad object that want to copy</param>
        /// <param name="ocopy">New InternalLoad object</param>
        internal void CoppyTemplateInternal(object oroot, object ocopy)
        {
            iInter++;
            foreach (PropertyInfo i in oroot.GetType().GetProperties())
            {
                object Copy = Activator.CreateInstance<object>();
                object value = oroot.GetType().GetProperty(i.Name).GetValue(oroot, null);
                i.SetValue(ocopy, value, null);
            }

            InternalLoad o1copy = (InternalLoad)ocopy;
            o1copy.lequip = ((InternalLoad)oroot).lequip;
            o1copy.sName = "Internal" + "-" + iInter;
            CheckInternalName(o1copy);
            linternalload.Add(o1copy);
        }

        public void CheckInternalName(InternalLoad i)
        {
            foreach (InternalLoad inter in linternalload)
            {
                if (i.sName == inter.sName)
                {
                    iInter++;
                    i.sName = "Internal-" + iInter;
                    CheckInternalName(i);
                }
            }
        }
        #endregion
        
        #region Template Construction
        /// <summary>
        /// Add a template about construction consist of Wall, Floor, Ceiling, Glass
        /// </summary>
        /// <param name="newwall">Wall object</param>
        /// <param name="newfloor">Floor object</param>
        /// <param name="newCeiling"></param>
        /// <param name="newGlass">Ceiling object</param>
        public void AddnewConstruction(object newwall, object newfloor, object newCeiling, object newGlass)
        {
            iCons++;
            Wall newwall1 = (Wall)newwall;
            Floor newfloor1 = (Floor)newfloor;
            Ceiling newCeiling1 = (Ceiling)newCeiling;
            Glass newGlass1 = (Glass)newGlass;

            lglass.Add(newGlass1);
            lceiling.Add(newCeiling1); ;
            lfloor.Add(newfloor1);
            lwall.Add(newwall1);
        }

        /// <summary>
        /// Delete a template about construction
        /// </summary>
        /// <param name="name">Name of template that want to delete</param>
        public void DeleteConstruction(string name)
        {
            try
            {
                Roof oroof1 = lroof.SingleOrDefault(rf => rf.sName.Trim().Equals(name));
                Wall owall1 = lwall.SingleOrDefault(rf => rf.sName.Trim().Equals(name));
                Floor ofloor1 = lfloor.SingleOrDefault(rf => rf.sName.Trim().Equals(name));
                Ceiling oceiling1 = lceiling.SingleOrDefault(rk => rk.sName.Trim().Equals(name));
                Glass oglass1 = lglass.SingleOrDefault(r => r.sName.Trim().Equals(name));
                lglass.Remove(oglass1);
                lceiling.Remove(oceiling1);
                lfloor.Remove(ofloor1);
                lwall.Remove(owall1);
                lroof.Remove(oroof1);
            }
            catch (Exception)
            {
                MessageBox.Show("Empty!");
            }
        }
        
        /// <summary>
        /// Copy a template about construction from a template
        /// </summary>
        /// <param name="sname">Name of template that want to copy</param>
        public void CopyConstruction(string sname)
        {
            iCons++;
            //  Copy glass
            Glass copyglass = Activator.CreateInstance<Glass>();
            Glass oglass1 = lglass.SingleOrDefault(r => r.sName.Trim().Equals(sname));
            foreach (PropertyInfo i in oglass1.GetType().GetProperties())
            {
                object value = oglass1.GetType().GetProperty(i.Name).GetValue(oglass1, null);
                i.SetValue(copyglass, value, null);
            }
            copyglass.sName = "Construction-" + iCons;
            CheckGlassName(copyglass);
            lglass.Add(copyglass);
            //  Copy ceiling 
            Ceiling copyCeiling = Activator.CreateInstance<Ceiling>();
            Ceiling oceiling1 = lceiling.SingleOrDefault(rk => rk.sName.Trim().Equals(sname));
            if (oceiling1 != null)
            {
                foreach (PropertyInfo i in oceiling1.GetType().GetProperties())
                {
                    object value = oceiling1.GetType().GetProperty(i.Name).GetValue(oceiling1, null);
                    i.SetValue(copyCeiling, value, null);

                }
                copyCeiling.sName = copyglass.sName;
                lceiling.Add(copyCeiling);
            }

            //  copy floor co van de ----------------------------->
            Floor copyFloor = Activator.CreateInstance<Floor>();
            Floor ofloor1 = lfloor.SingleOrDefault(rf => rf.sName.Trim().Equals(sname));/// ???
            foreach (PropertyInfo i in ofloor1.GetType().GetProperties())
            {
                object value = ofloor1.GetType().GetProperty(i.Name).GetValue(ofloor1, null);
                i.SetValue(copyFloor, value, null);

            }
            copyFloor.sName = copyglass.sName;
            lfloor.Add(copyFloor);
            //  copy Wall
            Wall copyWall = Activator.CreateInstance<Wall>();
            Wall owall1 = lwall.SingleOrDefault(rf => rf.sName.Trim().Equals(sname));
            foreach (PropertyInfo i in owall1.GetType().GetProperties())
            {
                object value = owall1.GetType().GetProperty(i.Name).GetValue(owall1, null);
                i.SetValue(copyWall, value, null);
            }
            copyWall.sName = copyglass.sName;

            lwall.Add(copyWall);
            //  coppy Roof
            Roof copyRoof = Activator.CreateInstance<Roof>();
            Roof oroof1 = lroof.SingleOrDefault(rf => rf.sName.Trim().Equals(sname));
            if (oroof1 != null)
            {
                foreach (PropertyInfo i in oroof1.GetType().GetProperties())
                {
                    object value = oroof1.GetType().GetProperty(i.Name).GetValue(oroof1, null);
                    i.SetValue(copyRoof, value, null);
                }
                copyRoof.sName = copyglass.sName;
                lroof.Add(copyRoof);
            }

        }

        /// <summary>
        /// Check overload name of Glass
        /// </summary>
        /// <param name="g">Glass object</param>
        public void CheckGlassName(Glass g)
        {
            foreach (Glass gl in lglass)
            {
                if (g.sName == gl.sName)
                {
                    iCons++;
                    g.sName = "Construction-" + iCons;
                    CheckGlassName(g);
                }
            }
        }
        #endregion

    }

}